# frozen_string_literal: true

module API
  class VulnerabilityExports < ::API::Base
    include ::API::Helpers::VulnerabilitiesHooks
    include ::Gitlab::Utils::StrongMemoize

    feature_category :vulnerability_management
    urgency :low

    helpers do
      def vulnerability_export
        strong_memoize(:vulnerability_export) do
          ::Vulnerabilities::Export.find(params[:id])
        end
      end

      def process_create_request_for(exportable)
        vulnerability_export = ::VulnerabilityExports::CreateService.new(
          exportable, current_user, format: params[:export_format]
        ).execute

        if vulnerability_export.persisted?
          status :created
          present vulnerability_export, with: EE::API::Entities::VulnerabilityExport
        else
          render_validation_error!(vulnerability_export)
        end
      end
    end

    before do
      authenticate!
    end

    namespace :security do
      resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
        params do
          requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
          optional :export_format,
            type: String, desc: 'The format of export to be generated',
            default: ::Vulnerabilities::Export.formats.each_key.first,
            values: ::Vulnerabilities::Export.formats.keys
        end
        desc 'Generate a project-level export' do
          success EE::API::Entities::VulnerabilityExport
        end

        post ':id/vulnerability_exports' do
          authorize! :create_vulnerability_export, user_project

          process_create_request_for(user_project)
        end
      end

      resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
        params do
          requires :id, type: String, desc: 'The ID of a group'
          optional :export_format,
            type: String, desc: 'The format of export to be generated',
            default: ::Vulnerabilities::Export.formats.each_key.first,
            values: ::Vulnerabilities::Export.formats.keys
        end
        desc 'Generate a group-level export' do
          success EE::API::Entities::VulnerabilityExport
        end

        post ':id/vulnerability_exports' do
          authorize! :create_vulnerability_export, user_group

          process_create_request_for(user_group)
        end
      end

      namespace do
        params do
          optional :export_format,
            type: String, desc: 'The format of export to be generated',
            default: ::Vulnerabilities::Export.formats.each_key.first,
            values: ::Vulnerabilities::Export.formats.keys
        end
        desc 'Generate an instance-level export' do
          success EE::API::Entities::VulnerabilityExport
        end
        post 'vulnerability_exports' do
          authorize! :create_vulnerability_export, current_user.security_dashboard

          process_create_request_for(current_user.security_dashboard)
        end
      end

      desc 'Get a single vulnerability export' do
        success EE::API::Entities::VulnerabilityExport
      end
      get 'vulnerability_exports/:id' do
        authorize! :read_vulnerability_export, vulnerability_export

        unless vulnerability_export.completed?
          ::Gitlab::PollingInterval.set_api_header(self, interval: 5_000)
          status :accepted
        end

        present vulnerability_export, with: EE::API::Entities::VulnerabilityExport
      end

      desc 'Download a single vulnerability export'
      get 'vulnerability_exports/:id/download' do
        authorize! :read_vulnerability_export, vulnerability_export

        if vulnerability_export.finished?
          present_carrierwave_file!(vulnerability_export.file)
        else
          not_found!('Vulnerability Export')
        end
      end
    end
  end
end
